using Microsoft.EntityFrameworkCore;
using UniversalAdmin.Application.Common;
using UniversalAdmin.Application.Dtos;
using UniversalAdmin.Application.Dtos.Article;
using UniversalAdmin.Application.Dtos.Log;
using UniversalAdmin.Application.Services.Interfaces;
using UniversalAdmin.Domain.Entities.App;
using UniversalAdmin.Domain.Repositories;

namespace UniversalAdmin.Application.Services.Implementations;

/// <summary>
/// 文章服务实现类
/// </summary>
public class ArticleService : IArticleService
{
    private readonly IRepositories<Article> _articleRepository;
    private readonly IRepositories<ArticleCategory> _categoryRepository;
    private readonly IRepositories<User> _userRepository;
    private readonly ILogService _logService;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="articleRepository">文章仓储</param>
    /// <param name="categoryRepository">分类仓储</param>
    /// <param name="userRepository">用户仓储</param>
    /// <param name="logService">日志服务</param>
    public ArticleService(
        IRepositories<Article> articleRepository,
        IRepositories<ArticleCategory> categoryRepository,
        IRepositories<User> userRepository,
        ILogService logService)
    {
        _articleRepository = articleRepository;
        _categoryRepository = categoryRepository;
        _userRepository = userRepository;
        _logService = logService;
    }

    public async Task<ArticleDto?> GetByIdAsync(Guid id)
    {
        var article = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .FirstOrDefaultAsync(a => a.Id == id && !a.IsDeleted);

        return article == null ? null : MapToDto(article);
    }

    public async Task<PagedResult<ArticleDto>> GetPagedAsync(PageRequestDto request)
    {
        var query = _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .Where(a => !a.IsDeleted)
            .OrderByDescending(a => a.CreatedAt);

        var total = await query.CountAsync();
        var items = await query
            .Skip((request.PageIndex - 1) * request.PageSize)
            .Take(request.PageSize)
            .ToListAsync();

        return new PagedResult<ArticleDto>
        {
            Items = items.Select(MapToDto).ToList(),
            Total = total,
            PageIndex = request.PageIndex,
            PageSize = request.PageSize
        };
    }

    public async Task<List<ArticleDto>> GetAllAsync()
    {
        var articles = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .Where(a => !a.IsDeleted)
            .OrderByDescending(a => a.CreatedAt)
            .ToListAsync();

        return articles.Select(MapToDto).ToList();
    }

    public async Task<List<ArticleDto>> GetByCategoryIdAsync(Guid categoryId)
    {
        var articles = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .Where(a => a.CategoryId == categoryId && !a.IsDeleted)
            .OrderByDescending(a => a.CreatedAt)
            .ToListAsync();

        return articles.Select(MapToDto).ToList();
    }

    public async Task<List<ArticleDto>> GetByStatusAsync(string status)
    {
        var articles = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .Where(a => a.Status == status && !a.IsDeleted)
            .OrderByDescending(a => a.CreatedAt)
            .ToListAsync();

        return articles.Select(MapToDto).ToList();
    }

    public async Task<ArticleDto> CreateAsync(CreateArticleDto createDto)
    {
        var article = new Article
        {
            Id = Guid.NewGuid(),
            Title = createDto.Title,
            Content = createDto.Content,
            Summary = createDto.Summary,
            Status = createDto.Status,
            CategoryId = createDto.CategoryId,
            UserId = createDto.UserId,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow,
            IsDeleted = false
        };

        var createdArticle = await _articleRepository.CreateAsync(article);

        // 写入操作日志
        await _logService.AddAsync(new CreateLogDto {
            UserId = createDto.UserId,
            Action = "Create",
            Resource = "Article",
            ResourceId = createdArticle.Id
        });

        // 重新查询以获取导航属性
        var result = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .FirstAsync(a => a.Id == createdArticle.Id);

        return MapToDto(result);
    }

    public async Task<ArticleDto> UpdateAsync(UpdateArticleDto updateDto)
    {
        var article = await _articleRepository.GetByIdAsync(updateDto.Id);
        if (article == null || article.IsDeleted)
            throw new ArgumentException("Article not found");

        article.Title = updateDto.Title;
        article.Content = updateDto.Content;
        article.Summary = updateDto.Summary;
        article.Status = updateDto.Status;
        article.CategoryId = updateDto.CategoryId;
        article.UserId = updateDto.UserId;
        article.UpdatedAt = DateTime.UtcNow;

        await _articleRepository.UpdateAsync(article);

        // 写入操作日志
        await _logService.AddAsync(new CreateLogDto {
            UserId = updateDto.UserId,
            Action = "Update",
            Resource = "Article",
            ResourceId = article.Id
        });

        // 重新查询以获取导航属性
        var result = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .FirstAsync(a => a.Id == article.Id);

        return MapToDto(result);
    }

    public async Task DeleteAsync(Guid id)
    {
        var article = await _articleRepository.GetByIdAsync(id);
        if (article == null || article.IsDeleted)
            throw new ArgumentException("Article not found");

        await _articleRepository.DeleteAsync(article);

        // 写入操作日志（无法获取操作者ID，需根据实际业务补充）
        await _logService.AddAsync(new CreateLogDto {
            Action = "Delete",
            Resource = "Article",
            ResourceId = article.Id
        });
    }

    public async Task<List<ArticleDto>> SearchAsync(string keyword)
    {
        var articles = await _articleRepository.Table
            .Include(a => a.Category)
            .Include(a => a.User)
            .Where(a => !a.IsDeleted &&
                       (a.Title.Contains(keyword) ||
                        (a.Content != null && a.Content.Contains(keyword)) ||
                        (a.Summary != null && a.Summary.Contains(keyword))))
            .OrderByDescending(a => a.CreatedAt)
            .ToListAsync();

        return articles.Select(MapToDto).ToList();
    }

    /// <summary>
    /// 将文章实体映射为DTO
    /// </summary>
    /// <param name="article">文章实体</param>
    /// <returns>文章DTO</returns>
    private static ArticleDto MapToDto(Article article)
    {
        return new ArticleDto
        {
            Id = article.Id,
            Title = article.Title,
            Content = article.Content,
            Summary = article.Summary,
            Status = article.Status,
            CategoryId = article.CategoryId,
            UserId = article.UserId,
            CreatedAt = article.CreatedAt,
            UpdatedAt = article.UpdatedAt,
            CategoryName = article.Category?.Name,
            UserName = article.User?.Username
        };
    }

    /// <summary>
    /// 启用文章
    /// </summary>
    /// <param name="id">文章ID</param>
    /// <returns>更新后的文章信息</returns>
    public async Task<dynamic> EnableArticleAsync(Guid id)
    {
        var article = await _articleRepository.GetByIdAsync(id);
        if (article == null || article.IsDeleted)
        {
            return ApiResult.Fail(404, "文章不存在");
        }
        if (article.IsActive)
        {
            return ApiResult.Fail(400, "文章已启用");
        }

        article.IsActive = true;
        article.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        article.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        await _articleRepository.UpdateAsync(article);

        return ApiResult.Success(new { ArticleId = article.Id }, "文章已启用");
    }

    public async Task<dynamic> DisableArticleAsync(Guid id)
    {
        var article = await _articleRepository.GetByIdAsync(id);
        if (article == null || article.IsDeleted)
        {
            return ApiResult.Fail(404, "文章不存在");
        }
        if(!article.IsActive)
        {
            return ApiResult.Fail(400, "文章已禁用");
        }

        article.IsActive = false;
        article.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        article.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取

        await _articleRepository.UpdateAsync(article);

        return ApiResult.Success(new { ArticleId = article.Id }, "文章已禁用");
    }
}
